﻿using System;
using System.Globalization;
using QAToolsAddin.GenericDialogs;
using QAToolsAddin.GenericDialogs.Fields;
using Excel = Microsoft.Office.Interop.Excel;

namespace QAToolsAddin.UI {
    class Insert {
        private readonly Excel.Application _excelapp;
        private readonly Excel.Range _range;
        private CultureInfo _culture;

        public Insert(Excel.Application application, CultureInfo culture) {
            try {
                _excelapp = application;
                _culture = culture;
                _range = application.ActiveWindow.RangeSelection;
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void FrequencyTableContinuous() {
            var f0 = new FieldRange("Data selection", "Data", _range, false);
            var f1 = new FieldNumber("Nb of classes", "Number of classes", 10, true);
            var f2 = new FieldNumber("Class precision", "Number of digits after the decimal point", 0, 0, 15, true);
            var inputbox = new InputBox(_excelapp, "Create frequency chart", f0, f1, f2);
            inputbox.RestoreSelectionOnExit = false;
            inputbox.Show(delegate {
                var rgsel = f0.Value;
                var nbClasses = (int)(f1.Value ?? 0);
                var precision = (int)(f2.Value ?? 0);
                var classes = Frequency.ComputeContinuousFrequencies(rgsel, nbClasses, precision);
                var nbValues = classes.Values.Length;
                var table = new object[nbValues + 1, 2];
                table[0, 0] = "Class";
                table[0, 1] = "Frequence";
                for (int i = 0; i < nbValues; i++) {
                    table[i + 1, 0] = classes.Names[i];
                    table[i + 1, 1] = classes.Values[i];
                }
                AddTableToNewSheet(table);
            });
        }

        public void FrequencyChartContinuous() {
            var f0 = new FieldRange("Data selection", "Data", _range, false);
            var f1 = new FieldNumber("Nb of classes", "Number of classes", 10, true);
            var f2 = new FieldNumber("Class precision", "Number of digits after the decimal point", 0, 0, 15, true);
            new InputBox(_excelapp, "Create frequency chart", f0, f1, f2).Show(delegate {
                var rgsel = f0.Value;
                var nbClasses = (int)(f1.Value ?? 0);
                var precision = (int)(f2.Value ?? 0);
                var classes = Frequency.ComputeContinuousFrequencies(rgsel, nbClasses, precision);
                var title = "min=" + classes.Min.ToString()
                                 + "  max=" + classes.Max.ToString()
                                 + "  µ=" + Math.Round(classes.Average, 8).ToString()
                                 + "  σ=" + Math.Round(classes.StandardDeviation, 8).ToString();
                var ch = AddColumnClusteredChart(classes.Names, classes.Values, title, "Class", "Frequency");
            });
        }

        public void FrequencyChartDiscete() {
            var f0 = new FieldRange("Data selection", null, _range, false);
            var f1 = new FieldRadioBT("Order by", new string[] { "Name", "Freq Asc", "Freq Desc" }, null, 0, true);
            new InputBox(_excelapp, "Create frequency chart", f0, f1).Show(delegate {
                var rgsel = f0.Value;
                var orderByFrequencyAsc = f1.Value == 1;
                var orderByFrequencyDesc = f1.Value == 2;
                var freq = Frequency.ComputeDisceteFrequencies(rgsel);
                if (orderByFrequencyAsc)
                    freq.SortByFrequenceAsc();
                else if (orderByFrequencyDesc)
                    freq.SortByFrequenceDesc();
                var ch = AddColumnClusteredChart(freq.Values, freq.Frequencies, null, "Value", "Frequency");
            });
        }

        public void FrequencyTableDiscete() {
            var f0 = new FieldRange("Data selection", null, _range, false);
            var f1 = new FieldRadioBT("Order by", new string[] { "Value", "Freq Asc", "Freq Desc" }, null, 0, true);
            var inputbox = new InputBox(_excelapp, "Create frequency chart", f0, f1);
            inputbox.RestoreSelectionOnExit = false;
            inputbox.Show(delegate {
                var rgsel = f0.Value;
                var orderByFrequencyAsc = f1.Value == 1;
                var orderByFrequencyDesc = f1.Value == 2;
                var freq = Frequency.ComputeDisceteFrequencies(rgsel);
                if (orderByFrequencyAsc)
                    freq.SortByFrequenceAsc();
                else if (orderByFrequencyDesc)
                    freq.SortByFrequenceDesc();

                var nbValues = freq.Frequencies.Length;
                var table = new object[nbValues + 1, 2];
                table[0, 0] = "Value";
                table[0, 1] = "Frequence";
                for (int i = 0; i < nbValues; i++) {
                    table[i + 1, 0] = freq.Values[i];
                    table[i + 1, 1] = freq.Frequencies[i];
                }
                AddTableToNewSheet(table);
            });
        }

        private Excel.Chart AddColumnClusteredChart(object valuesX, object valuesY, string title, string labelX, string labelY) {
            _excelapp.ScreenUpdating = false;
            var selection = _excelapp.Selection as Excel.Range;
            try {
                selection.Resize[2, 1].Select();
                Excel.Chart ch;
#if V11
                 ch = (Excel.Chart)_excelapp.Charts.Add(Type.Missing, Type.Missing, Type.Missing, Type.Missing);
#else
                ch = ((Excel.Worksheet)_excelapp.ActiveSheet).Shapes.AddChart(Excel.XlChartType.xlColumnClustered).Chart;
#endif
                ch.ChartType = Excel.XlChartType.xlColumnClustered;
                var serie = (Excel.Series)ch.SeriesCollection(1);
                serie.Formula = "=SERIES(,0,0,1)";
                serie.XValues = valuesX;
                serie.Values = valuesY;
                serie.ApplyDataLabels();
                ch.Legend.Delete();
                if (!string.IsNullOrEmpty(title)) {
                    ch.HasTitle = true;
                    ch.ChartTitle.Font.Size = 10;
                    ch.ChartTitle.Text = title;
                } else {
                    ch.HasTitle = false;
                }
                if (!string.IsNullOrEmpty(labelX)) {
                    var horizontalAxis = (Excel.Axis)ch.Axes(Excel.XlAxisType.xlCategory, Excel.XlAxisGroup.xlPrimary);
                    horizontalAxis.HasTitle = true;
                    horizontalAxis.AxisTitle.Characters.Text = labelX;
                }
                if (!string.IsNullOrEmpty(labelY)) {
                    var verticalAxis = (Excel.Axis)ch.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlPrimary);
                    verticalAxis.HasTitle = true;
                    verticalAxis.AxisTitle.Characters.Text = labelY;
                }
#if V11
                ch.Location(Excel.XlChartLocation.xlLocationAsObject, selection.Worksheet.Name);
#endif
                return ch;
            } finally {
                selection.Select();
                _excelapp.ScreenUpdating = true;
            }
        }

        private void AddTableToNewSheet(object[,] table) {
            var sheet = (Excel.Worksheet)_excelapp.ActiveWorkbook.Sheets.Add(After: _excelapp.ActiveSheet);
            var rg = sheet.Cells.Resize[table.GetLength(0), table.GetLength(1)];
            rg.Value = table;
#if V11
            sheet.ListObjects.Add(SourceType: Excel.XlListObjectSourceType.xlSrcRange, Source: rg, XlListObjectHasHeaders: Excel.XlYesNoGuess.xlYes);
#else
            sheet.ListObjects.AddEx(SourceType: Excel.XlListObjectSourceType.xlSrcRange, Source: rg, XlListObjectHasHeaders: Excel.XlYesNoGuess.xlYes);
#endif

        }

    }
}
